/*****************************************************************************
*
*  @file     UartDriver.c
*  @brief    Uart驱动
*            1. 负责实现Uart驱动
*
*  @author   潘学林
*  @email                                        
*  @version  V0.000
*  @date     2022/4/20
*  @license  /
*----------------------------------------------------------------------------*
*  Remark         : Description                                              *
*----------------------------------------------------------------------------*
*  Change History :                                                          *
*  <Date>     | <Version> | <Author>       | <Description>                   *
*----------------------------------------------------------------------------*
*  2022/4/20  | 0.000     | 潘学林         | 创建文件                        *
*----------------------------------------------------------------------------*
*
*****************************************************************************/

/* Includes ------------------------------------------------------------------*/

#include "UartDriver.h"

/* Micros/Enumerate/Structures -----------------------------------------------*/

/* Variables -----------------------------------------------------------------*/

/* 串口数据发送缓冲区 */
static uint8 uartTxTestBuff[] = "Init Information.\r\n";
/* 串口数据接收缓冲区 */
static uint8 uartRxTestBuff[USART1_RX_LENGTH];

/* Functions -----------------------------------------------------------------*/

/*****************************************
* 内部函数
*****************************************/
/**
  * @brief  Uart1初始化
  * @param  None
  * @retval None
  */
static void UartDriver_Uart1Init(void)
{
	/* enable GPIO clock */
	rcu_periph_clock_enable(RCU_GPIOA);

	/* enable USART clock */
	rcu_periph_clock_enable(RCU_USART1);

	/* connect port to USARTx_Tx */
	gpio_init(RS485_TX_Port, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, RS485_TX_Pin);

	/* connect port to USARTx_Rx */
	gpio_init(RS485_RX_Port, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, RS485_RX_Pin);

	/* USART configure */
	usart_deinit(USART1);
	usart_baudrate_set(USART1, 115200U);
	usart_receive_config(USART1, USART_RECEIVE_ENABLE);
	usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
	usart_enable(USART1);
}

/**
  * @brief  Dma初始化
  * @param  None
  * @retval None
  */
static void UartDriver_DmaInit(void)
{
	dma_parameter_struct dma_init_struct;

	/* enable DMA0 */
	rcu_periph_clock_enable(RCU_DMA0);
	/* deinitialize DMA channel3(USART1 tx) */
	dma_deinit(DMA0, DMA_CH6);
	dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
	dma_init_struct.memory_addr = (uint32)uartTxTestBuff;
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
	dma_init_struct.number = (sizeof(uartTxTestBuff) / sizeof(uint8) - 1);
	dma_init_struct.periph_addr = USART1_DATA_ADDRESS;  
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
	dma_init(DMA0, DMA_CH6, &dma_init_struct);
	/* configure DMA mode */
	dma_circulation_disable(DMA0, DMA_CH6);
	dma_memory_to_memory_disable(DMA0, DMA_CH6);

	dma_deinit(DMA0, DMA_CH5);
	dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
	dma_init_struct.memory_addr = (uint32)uartRxTestBuff;
	dma_init(DMA0, DMA_CH5, &dma_init_struct);
	/* configure DMA mode */
	dma_circulation_disable(DMA0, DMA_CH5);
	dma_memory_to_memory_disable(DMA0, DMA_CH5);
	
	/* enable USART1 DMA channel transmission and reception */
	dma_channel_enable(DMA0, DMA_CH6);
	dma_channel_enable(DMA0, DMA_CH5);
	
	/* USART DMA enable for transmission */
	usart_dma_transmit_config(USART1, USART_DENT_ENABLE);
	/* USART DMA enable for transmission */
	usart_dma_receive_config(USART1, USART_DENR_ENABLE);
}

/**
  * @brief  串口发送
  * @param  None
  * @retval None
  */
static void UartDriver_Transmit_DMA(uint8 *dataAddr, uint16 length)
{
	dma_parameter_struct dma_init_struct;
	
	/* deinitialize DMA channel3(USART1 tx) */
	dma_deinit(DMA0, DMA_CH6);
	dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
	dma_init_struct.memory_addr = (uint32)dataAddr;
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
	dma_init_struct.number = length;
	dma_init_struct.periph_addr = USART1_DATA_ADDRESS;
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
	dma_init(DMA0, DMA_CH6, &dma_init_struct);
	/* configure DMA mode */
	dma_circulation_disable(DMA0, DMA_CH6);
	dma_memory_to_memory_disable(DMA0, DMA_CH6);
	
	/* enable USART1 DMA channel transmission and reception */
	dma_channel_enable(DMA0, DMA_CH6);
	dma_channel_enable(DMA0, DMA_CH5);
	
	/* USART DMA enable for transmission */
	usart_dma_transmit_config(USART1, USART_DENT_ENABLE);
}

/**
  * @brief  串口接收
  * @param  None
  * @retval None
  */
static void UartDriver_Receive_DMA(uint8 *dataAddr, uint16 length)
{
	dma_parameter_struct dma_init_struct;

	dma_deinit(DMA0, DMA_CH5);
	dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
	dma_init_struct.memory_addr = (uint32)dataAddr;
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
	dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
	dma_init_struct.number = length;
	dma_init_struct.periph_addr = USART1_DATA_ADDRESS;
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
	dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
	dma_init(DMA0, DMA_CH5, &dma_init_struct);
	/* configure DMA mode */
	dma_circulation_disable(DMA0, DMA_CH5);
	dma_memory_to_memory_disable(DMA0, DMA_CH5);
	
	/* enable USART1 DMA channel transmission and reception */
	dma_channel_enable(DMA0, DMA_CH5);
	
	/* USART DMA enable for receive */
	usart_dma_receive_config(USART1, USART_DENR_ENABLE);
}

/*****************************************
* 接口函数
*****************************************/

/**
  * @brief  Uart驱动初始化
  * @param  None
  * @retval None
  */
void UartDriver_Init(void)
{
	/* 1. 串口初始化 */
	UartDriver_Uart1Init();
	
	/* 2. DMA初始化 */
	UartDriver_DmaInit();
}

/**
  * @brief  Uart发送处理
  * @param  None
  * @retval None
  */
void UartDriver_SendProcess(void)
{
	if (dma_flag_get(DMA0, DMA_CH6, DMA_INTF_FTFIF) == SET)
	{
		dma_flag_clear(DMA0, DMA_CH6, DMA_INTF_FTFIF);
	
		UartDriver_Transmit_DMA((uint8*)"---Test Information---", (sizeof("---Test Information---") / sizeof(uint8) - 1));
	}
	else
	{
		/* nop */
	}
}

/**
  * @brief  Uart接收处理
  * @param  None
  * @retval None
  */
void UartDriver_ReceiveProcess(void)
{
	if (dma_flag_get(DMA0, DMA_CH5, DMA_INTF_FTFIF) == SET)
	{
		dma_flag_clear(DMA0, DMA_CH5, DMA_INTF_FTFIF);
	
		UartDriver_Receive_DMA(uartRxTestBuff, USART1_RX_LENGTH);
	}
	else
	{
		/* nop */
	}
}

/********************************* END OF FILE ********************************/
